home *** CD-ROM | disk | FTP | other *** search
/ Cracking 2 / Cracking II..iso / Texty / crackme / TEST4TUT.TXT < prev    next >
Encoding:
Text File  |  1997-01-05  |  27.6 KB  |  732 lines

  1.                  How to crack "uncrackable" test4 by LordByte
  2.  
  3.                             by Crook, 14 June 1997
  4.                            updated on 8 August 1997
  5.  
  6.  
  7.                                 What is test4?
  8.  
  9.  
  10.      Test4  is  fourth  in  row of small challanges from LordByte. This one is
  11. 1251 bytes long and it was uncrackable for some time (I don't know when it was
  12. written).  Quoting author of this test "the only purpose of it is to challenge
  13. superior Crackers. ONLY password can be accepted. NO PATCH can qualify!".
  14.      The  technique  used  in  this  test  is  called  one-time  pad. If every
  15. variation of this method is so easily cracked, you can forget about it.
  16.  
  17.                        Target audience of this tutorial
  18.  
  19.  
  20.      Everyone  wishing  to  learn  something. You MUST know assembly and basic
  21. math before trying to read this. Of course you can read without even trying to
  22. think  how  was it done, but it's just wasted time. The knowledge of C is also
  23. an advantage, because I'm going to show you program in C which does whole work
  24. for us.
  25.  
  26.  
  27.                                  Brute force
  28.  
  29.  
  30.      When there are passwords around there is also a brute force approach. But
  31. after short calculations I've started to think about some smarter method.
  32.      There  are  2^96  possible  passwords.  Assuming  that  you've  written a
  33. program,  which can check 1 million passwords per second, it means you have to
  34. wait 2^49 years, until it finishes.
  35.      After  I've  cracked  test4  I  realized  that  there  are  2^60 possible
  36. passwords.  But  even knowing this brute force is slow: statisticaly for every
  37. 2^36 wrong passwords, there is one good. Checking million passwords per second
  38. it would take about 18 hours. My method takes about 1 minute on 486DX/33... ;)
  39.                                          [This paragraph was dedicated to ACP]
  40.  
  41.                                  Let's start
  42.  
  43.  
  44.      The  first  thing  you  must  do is to understand the test4.com. Run your
  45. favourite  debugger  (Turbo  Debugger will be enough) and look deeply into the
  46. code,  trying  to  understand  what's  doing  inside  of  it.  Without perfect
  47. understanding  of method password is processed you won't be able to understand
  48. further  parts  of  this  tut. However, below is disassembly of vital parts of
  49. test4.com to help you with this task.
  50.  
  51.      mov dx, offset text1
  52.      call show_text
  53.      call hook_int
  54.      mov dx, offset text2
  55.      call show_text
  56.      mov dx, offset buffer
  57.      mov ax, 0A00h         ; get password
  58.      int 21h
  59.  
  60.      This  is  the start of TEST4. You're writing some messages on the screen,
  61. hooking  time interrupt to blink the frame (patched by me, so there will be no
  62. such   effect),  and  getting  password  into  the  buffer.  As  far,  nothing
  63. complicated.
  64.  
  65. start:
  66.      mov ebx, 0
  67. get_4_bytes_out_of_password_into_eax:
  68.      lea esi, [ebx+offset password]
  69.      lea edi, table
  70.      mov eax, [esi]
  71.      cmp ah, 0Dh
  72.      jz manipulate_with_password
  73. do_xor:
  74.      xor [edi], eax
  75.      rol eax, 2
  76.      inc edi
  77.      cmp dword ptr [edi+4], 0
  78.      jnz do_xor
  79.      inc ebx
  80.      jmp short get_4_bytes_out_of_password_into_eax
  81.  
  82.      Let me tell you what's going there. In start you're zeroing ebx, which is
  83. index register from now on - it's char number in password. Next, load into esi
  84. address  of  char  number  ebx in password, and into edi address of the table,
  85. which will be xored by the values depending on password. Then you're getting 4
  86. bytes  of  the  password  into  eax  and  checking if you're on the end of the
  87. password. If you are, then you must change password (of course by xoring it by
  88. some values).
  89.      Code  after  do_xor label is the main part of this program. Four bytes in
  90. the  table  are xored by the eax. Then eax is rolled 2 bits to the left, index
  91. in  the table (edi) is increased by one. You don't want to xor anything except
  92. the  table, so there must be checking if you're out of table boundaries, which
  93. is  done  in the next line. If you've whole table xored, the ebx (index in the
  94. password) is increased by one, and the whole story begins once again.
  95.  
  96. manipulate_with_password:
  97.      lea esi, table
  98.      mov eax, [esi]
  99.      lea esi, password
  100.      xor [esi], eax
  101.      xor [esi+4], eax
  102.      xor [esi+8], eax
  103.      inc pass_count
  104.      cmp pass_count, 3
  105.      jnz not_3_pass
  106.      mov xor_key, eax
  107. not_3_pass:
  108.      cmp pass_count, 5
  109.      jnz start
  110.  
  111.      This part is easy to understand: get first four bytes from the table into
  112. eax,  then xor password with it. Next increase pass count. If it's third pass,
  113. you're storing eax for later use (to decrypt ciphered message). If it's fifth,
  114. you can go further.
  115.  
  116.      mov ebx, 0
  117. check:
  118.      lea esi, [ebx+offset table]
  119.      lea edi, [ebx+offset target_table]
  120.      mov eax, [esi]
  121.      xor [edi], eax
  122.      jnz bad_password
  123.      add ebx, 4
  124.      cmp dword ptr [esi+4], 0
  125.      jnz check
  126.  
  127.      This  piece of code is also pretty obvious - the good password transforms
  128. original  table  into  target_table  (also  stored  in  file). Checking if the
  129. password  is good is reduced to check if both, table and target_table, are the
  130. same.  Above  snippet  of code does just that - if the tables are different it
  131. means the password is bad. If they're the same - OK, user is a good cracker ;)
  132.  
  133.      mov si, good_password_message
  134.      mov eax, xor_key
  135. xor_message:
  136.      xor [si], al
  137.      rol eax, 4
  138.      inc si
  139.      cmp byte ptr [si], 24h
  140.      jnz xor_message
  141.      mov dx, good_password_message
  142.      call show_text
  143.      jmp short end_program
  144.  
  145.      Here  the  text  is  decrypted. The algorithm is very simple, however you
  146. should study it, because it's important part of the crack.
  147.      If you perfectly understand what is going on you can read furher - if you
  148. have  any  doubts  then  read this again and again until you understand. It is
  149. strongly recommended to know exactly how it works.
  150.  
  151.  
  152.                Main idea of crack (or, should I say, croock ;)
  153.  
  154.  
  155.      The  target_table  can  be  presented  as a row of bits. Nothing exciting
  156. about  this. But it can be also presented as value (0 or 1) and number of bits
  157. from the password it is xored. And that's exciting, because it's the main idea
  158. which  allowed  me to make C program to crack this program. Don't worry if you
  159. don't understand anything - I'll show you an example.
  160.      Let's  assume  you've got target value: 0xe9, and the source value: 0x5f.
  161. You've got also a "magic box" which transforms source value into target value:
  162.  
  163. source value (0x5f) --> [MAGIC BOX] --> target_value (0xe9)
  164.  
  165.      You  also know that magic box uses just xor to transform values. You even
  166. know  the  schema  of this xors, but we don't know the password. Let's say the
  167. password has 4 bits.
  168.  
  169. 0 bit from source xored by 0, 1, 3 bits from password gives 0 bit from target
  170. 1 bit from source xored by 1, 2, 3 bits from password gives 1 bit from target
  171. 2 bit from source xored by 0 bit from password gives 2 bit from target
  172. 3 bit from source xored by 1, 2 bits from password gives 3 bit from target
  173. 4 bit from source xored by 3 bit from password gives 4 bit from target
  174. 5 bit from source xored by 2, 3 bits from password gives 5 bit from target
  175. 6 bit from source xored by 0, 3 bits from password gives 6 bit from target
  176. 7 bit from source xored by 1, 3 bits from password gives 7 bit from target
  177.  
  178.      This  allows  us  to  recover the password. How? By creating eight linear
  179. equations. Symbol 0s means bit 0 from source, 7t - seventh bit from target, 2p
  180. - second bit from password. Above 8 conditions can be written as:
  181.  
  182. 0s xor 0p xor 1p xor 3p = 0t
  183. 1s xor 1p xor 2p xor 3p = 1t
  184. 2s xor 0p = 2t
  185. 3s xor 1p xor 2p = 3t
  186. 4s xor 3p = 4t
  187. 5s xor 2p xor 3p = 5t
  188. 6s xor 0p xor 3p = 6t
  189. 7s xor 1p xor 3p = 7t
  190.  
  191.      You  know source and targets bits so you can change 0s, 1s and so on into
  192. values:
  193.  
  194. (0x5f)           (0xe9)
  195.  
  196. 1 xor 0p, 1p, 3p = 1
  197. 1 xor 1p, 2p, 3p = 0
  198. 1 xor 0p =         0
  199. 1 xor 1p, 2p =     1
  200. 1 xor 3p =         0
  201. 0 xor 2p, 3p =     1
  202. 1 xor 0p, 3p =     1
  203. 0 xor 1p, 3p =     1
  204.  
  205.      By xoring both sides of equations by the values on the left side (this is
  206. basic math I've written earlier) you get:
  207.  
  208. 0p xor 1p xor 3p = 0
  209. 1p xor 2p xor 3p = 1
  210. 0p               = 1
  211. 1p xor 2p        = 0
  212. 3p               = 1
  213. 2p xor 3p        = 1
  214. 0p xor 3p        = 0
  215. 1p xor 3p        = 1
  216.  
  217.      Solving  this set of equations (using whichever method - e.g. using sheet
  218. of paper and a pencil ;) you get:
  219.  
  220. 0p = 1
  221. 1p = 0
  222. 2p = 0
  223. 3p = 1, so the password is 1001.
  224.  
  225.      I  think the main idea is clear now: you must build up a schema of xoring
  226. for every bit in the table, on then solve the equations. This is not so simple
  227. as  in the above examples - the table is 122 bytes long, so it's 976 bits, and
  228. for  each  you must build up an equations. Then you must solve these equations
  229. using some smart method, because solving 976 equations on sheet of paper would
  230. take  ages. Using some programming language (e.g. C) you are now able to write
  231. a program which will do crack for us.
  232.  
  233.  
  234.                               Hey, wait a minute
  235.  
  236.  
  237.      Above  explanations  are true, but you're forgetting about one thing - in
  238. the  third  pass  (if you don't remember - please study the code again) you're
  239. storing  eax into memory, and then this value is used to decipher some crypted
  240. text.  Who  can  guearantee us, that password which will transform target into
  241. target_table will also generate valid key for decrypting this text? That's why
  242. you  must build 32 equations extra for this condition. Finally you've got 1008
  243. instead of 976 equations.
  244.  
  245.  
  246.                                Finding xor_key
  247.  
  248.  
  249.      All  right,  but  how  can  you find this key? The answer is simple - the
  250. decrypted  text  should end with three bytes 0xd, 0xa, 0x24 (if you don't know
  251. why,  study  some info about int21/ah=9 function). The layout of the test4.com
  252. in memory looks like this:
  253.  
  254. 0100 code
  255. 02c4 buffer for password
  256. 02d3 "Enter password" text
  257. 02ea table
  258. 036a ciphered text
  259. 03b5 target_table
  260.  
  261.      target_table  is  zeroed  after comparing function (check label) if table
  262. and  target_table  are  the same, so the last three bytes of the ciphered text
  263. are  stored  in  03b2,  03b3  and 03b4 offsets. It's 0x9e, 0x40 and 0xfe. 0x9e
  264. should be xored to 0xa, 0x40 to 0xd and 0xfe to 0x24. That means 0x9e is xored
  265. by 0x94, 0x40 by 0x4d and 0xfe by 0xda.
  266.  
  267. 0x9e xor 0x94 = 0xa
  268. 0x40 xor 0x4d = 0xd
  269. 0xfe xor 0xda = 0x24
  270.  
  271.      In  eax  you've  got  the  key.  I'm assuming every letter is a nibble (4
  272. bits):
  273.  
  274. eax: abcdefgh
  275. al: gh
  276.  
  277.      So, first byte is xored by gh. Then eax is rolled 4 bits left:
  278.  
  279. eax: bcdefgha
  280. al: ha
  281.  
  282.      Second  byte  is  xored  by  ha, and so on. Look what happens when you're
  283. xoring ninth byte:
  284.  
  285. 1: abcdefgh
  286. 2: bcdefgha
  287. 3: cdefghab
  288. 4: defghabc
  289. 5: efghabcd
  290. 6: fghabcde
  291. 7: ghabcdef
  292. 8: habcdefg
  293. 9: abcdefgh
  294.  
  295.      It  means  that key is same for bytes which are in the same column of the
  296. dump pane in TD.
  297.  
  298. DS:036A D7 22 B4 C1 13 71 70 EC <-- This is dump panel from TD
  299. DS:0372 F8 2C AE .. .. .. .. ..
  300. ...
  301. DS:03B2 9E 40 FE .. .. .. .. ..
  302.  
  303.      Xoring  D7,22,B4  by  94,4D,DA you get "Con". This should be beginning of
  304. the  "Congratulations"  string.  Let's go further: xor D7,22,B4,C1,13,71,70,EC
  305. with  "Congratu".  You're getting 8 bytes: 94,4D,DA,A6,61,10,09,99. You've got
  306. whole  information,  but  you  must  "pack" 8 bytes into 4. The lowest byte is
  307. 0x94.  Then, after ROL EAX,4 you should get 0x4d in al. That means the highest
  308. nibble is 0xd. After next ROL al is 0xda, so the second highest nibble is 0xa.
  309. Going  further,  you  can reconstruct the key, which is 0xda610994. Using this
  310. value, you can decrypt text:
  311. "Congratulations. You have done the what cannot be done .. Tell me how ?!"
  312.      Wow! First success! You haven't done anything spectacular by now, but you
  313. will, don't worry ;)
  314.  
  315.  
  316.                                    Program
  317.  
  318.  
  319. Whole source code for testcrk.c which is the main part of my work is included
  320. in ZIP file, UUENCODED at the end of this file. Below are the main parts of
  321. the code, commented as good as I can.
  322.  
  323. ------------------------------------------------------------------------------
  324. #define KEYCHARS 16
  325. #define KEYBITS KEYCHARS * 8
  326. #define XORCHARS 122
  327. #define XORBITS XORCHARS * 8
  328. #define EQUATIONS XORBITS + 32
  329. #define KEYSIZE KEYBITS * (KEYBITS + 1)
  330. #define XORSIZE XORBITS * (KEYBITS + 1)
  331. ------------------------------------------------------------------------------
  332.  
  333. KEYCHARS - number of chars in the buffer
  334. KEYBITS - number of bits in the buffer
  335. XORCHARS - size of table
  336. XORBITS - number of bits in the table
  337. EQUATIONS - number of equations to solve
  338. KEYSIZE - size of whole TabKey table
  339. XORSIZE - size of whole TabCipher table
  340.  
  341. ------------------------------------------------------------------------------
  342. char huge TabKey[KEYBITS][KEYBITS+1];         // password
  343. char huge TabCipher[EQUATIONS][KEYBITS+1];    // table for XOR
  344. char AktKey[32][KEYBITS+1];                   // current key
  345. char Temp[2][KEYBITS+1];                      // temporary for ROL
  346. char TabPass[KEYBITS];                        // password divided into bits
  347. char password[KEYCHARS];
  348. char TempEqu[12 * 8 + 1];                     // temp for swap_equ
  349. unsigned char solved[EQUATIONS];
  350. ------------------------------------------------------------------------------
  351.  
  352. TabKey - table where the key (whole 16-char buffer) will be stored, divided
  353.          into bits. If the n-th bit is set to 1 (0 < n < KEYBITS), that means
  354.          this bit is XORed by n-th from the buffer. If the KEYBITS bit is set
  355.          it means it is XORed by 1.
  356. TabCipher - table where the table is stored, divided into bits. Format same as
  357.             above.
  358. AktKey - key divided into bits (value stored in eax, used to XOR bytes from
  359.          table). Format same as above.
  360. Temp - temporary table to perform ROL EAX,2 on AktKey
  361. TabPass - password divided into bits. If the n-th bit is set, it means the
  362.           n-th bit in the password is 1. If not - the bit is 0. WARNING: I've
  363.           implemented other bit numbering system: bit 0 is the most
  364.           significant bit, and the (KEYBITS-1) is the least significant.
  365. password - password in bytes. Used by do_test() routine. Just for testing
  366.            purposes. Left for historical reasons ;)
  367. TempEqu - temporary swap space for swap_equ functions, which swaps places of
  368.           two equations
  369. solved - if the n-th element of this table is set, that means it was used to
  370.          calculate some bit in password. More details on solve() functions
  371.          comment
  372.  
  373. ------------------------------------------------------------------------------
  374. FILE *org;
  375. char passsize;
  376. char size_pass[] = {11, 14, 14, 14};
  377. char passchars = 0, passbits = 0;
  378. char yesorno;
  379. ------------------------------------------------------------------------------
  380.  
  381. org - file struct, used on file operations
  382. passsize - current password size, more details on create_table() function
  383.            comment
  384. size_pass - table to get passsize from, more details on create_table()
  385.             function comment
  386. passchars - number of letters in password. Set by user.
  387. passbits - number of bits in password. Set by user.
  388.  
  389. ------------------------------------------------------------------------------
  390. void create_table()
  391. ------------------------------------------------------------------------------
  392.  
  393. Function which is the alfa & omega here. Creates the XOR schema.
  394.  
  395. ------------------------------------------------------------------------------
  396. int i, j;
  397. unsigned char mask, chr, byte[XORCHARS];
  398. long cipherpos;
  399. int pass, keychar, bits, xor_char;
  400. unsigned char buffer[KEYBITS + 1];
  401. ------------------------------------------------------------------------------
  402.  
  403. i, j - counters, used in various for loops
  404. mask, chr, byte, cipherpos - used when loading ORG.DAT
  405. pass - pass index
  406. keychar - char index from the password processed
  407. bits - bit index when xoring table by eax
  408. xor_char - char index when xoring table by eax
  409. buffer - buffer used when reading from CIPHER.DAT
  410.  
  411. ------------------------------------------------------------------------------
  412. if ((org = fopen("CIPHER.DAT", "rb")) != NULL)
  413. {
  414.   fread(byte, 1, 1, org);
  415.   if (byte[0] == passchars)
  416.   {
  417.     printf("reading from CIPHER.DAT...\n");
  418.     for (i = 0; i < EQUATIONS; i++)
  419.     {
  420.       fread(buffer, KEYBITS+1, 1, org);
  421.       // we cannot use _fmemcpy, coz it fails sometimes on huge tables
  422.       for (j = 0; j <= KEYBITS; j++)
  423.         TabCipher[i][j] = buffer[j];
  424.     }
  425.     fclose(org);
  426.     return;
  427.   }
  428. }
  429. ------------------------------------------------------------------------------
  430.  
  431.      Above  piece  of  code  loads  the  equations from CIPHER.DAT, instead of
  432. creating them from scratch. This file is created on the end of create_table().
  433. Speeds up the process of cracking after first time.
  434.  
  435. ------------------------------------------------------------------------------
  436. memset(TabPass, 0, KEYBITS);
  437. _fmemset(TabKey, 0, KEYSIZE);   // initiate TabKey
  438. for (i = 0; i < passbits; i++)  // set passbits bits
  439.   TabKey[i][i] = 1;
  440. TabKey[passchars*8][KEYBITS] = 0;   // char after password is 0x0d
  441. ...
  442. TabKey[13*8][KEYBITS] = 0;         // 13th char is 0x0a
  443. ...
  444. TabKey[14*8][KEYBITS] = 0;         // on 14th pos we've got 0x0d
  445. ...
  446. TabKey[15*8][KEYBITS] = 0;         // on 15th there's is 0x20
  447. ...
  448. passsize = passchars;
  449. ------------------------------------------------------------------------------
  450.  
  451. Initialization code. Sets up bits like in the original test4.com:
  452.  
  453. x|x|x|x|x|x|x|x|x|x|x|x|0xd|0xa|0x0d|0x20|
  454. this is the case when the password has 12 chars.
  455.  
  456. x|x|x|x|x|x|x|x|x|x|0xd|0|0|0xa|0x0d|0x20|
  457. it looks like this, when the password has 10 chars.
  458.  
  459. ------------------------------------------------------------------------------
  460. if ((org = fopen("ORG.DAT", "rb")) == NULL)
  461. {
  462.   printf("ORG.DAT not found!\n");
  463.   exit(255);
  464. }
  465.  
  466. _fmemset(TabCipher, 0, XORSIZE);  // initiate TabCipher
  467. cipherpos = 0;
  468. fread(byte, XORCHARS, 1, org);
  469. fclose(org);
  470. for (i = 0; i < XORCHARS; i++)
  471.   for (mask = 0x80; mask != 0; mask >>= 1)
  472.   {
  473.     if ((byte[i] & mask) == mask) TabCipher[cipherpos][KEYBITS] = 1;
  474.     cipherpos++;
  475.   }
  476. ------------------------------------------------------------------------------
  477.  
  478.      Loads  the  ORG.DAT  into  memory and transforms it into bits. ORG.DAT is
  479. table stored in separate file.
  480.  
  481. ------------------------------------------------------------------------------
  482. for (pass = 0; pass < 5; pass++)
  483. {
  484.   for (keychar = 0; keychar < (passsize - 1); keychar++)
  485.   {
  486.     putch('.');
  487.     memcpy(AktKey, TabKey[keychar*8+24], 8*(KEYBITS+1)); // get current key
  488.     memcpy(AktKey[8], TabKey[keychar*8+16], 8*(KEYBITS+1)); // but reversed
  489.     memcpy(AktKey[16], TabKey[keychar*8+8], 8*(KEYBITS+1));
  490.     memcpy(AktKey[24], TabKey[keychar*8], 8*(KEYBITS+1));
  491. ------------------------------------------------------------------------------
  492.  
  493. When you execute instruction
  494.   MOV EAX,[ESI]
  495. and in [ESI] you've got
  496.   ABCD
  497. where A, B, C, D are bytes, in EAX you get
  498.   DCBA
  499. That's why you must copy to AktKey using this strange-looking code.
  500.  
  501. ------------------------------------------------------------------------------
  502. for (xor_char = 0; xor_char <= (XORCHARS - 4); xor_char++)
  503. {
  504.   for (bits = 24; bits < 32; bits++)
  505.     do_xor(TabCipher[xor_char * 8 + bits - 24], AktKey[bits]);
  506.   for (bits = 16; bits < 24; bits++)
  507.     do_xor(TabCipher[xor_char * 8 + bits - 8], AktKey[bits]);
  508.   for (bits = 8; bits < 16; bits++)
  509.     do_xor(TabCipher[xor_char * 8 + bits + 8], AktKey[bits]);
  510.   for (bits = 0; bits < 8; bits++)
  511.     do_xor(TabCipher[xor_char * 8 + bits + 24], AktKey[bits]);
  512.   memcpy(Temp, AktKey, 2 * (KEYBITS + 1));
  513.   memmove(AktKey, AktKey[2], 30 * (KEYBITS + 1));
  514.   memcpy(AktKey[30], Temp, 2 * (KEYBITS + 1));
  515. }
  516. ------------------------------------------------------------------------------
  517.  
  518.      Does  right  XORing.  Because  the XOR [ESI], EAX behaves like written in
  519. above  comment  we  have  to  do  it  also  in  reverse byte order. The next 3
  520. instructions are equivalent to ROL EAX,2
  521.  
  522. ------------------------------------------------------------------------------
  523. for (bits = 0; bits < 32; bits++)
  524. {
  525.   do_xor(TabKey[bits], TabCipher[bits]);
  526.   do_xor(TabKey[32 + bits], TabCipher[bits]);
  527.   do_xor(TabKey[64 + bits], TabCipher[bits]);
  528. }
  529. ------------------------------------------------------------------------------
  530.  
  531. After finished pass you must XOR password with the beginning of table.
  532.  
  533. ------------------------------------------------------------------------------
  534. if (pass == 2) set_eax();
  535. if (passsize < 12) passsize = 14;
  536. ------------------------------------------------------------------------------
  537.  
  538.      When  it's  third  pass  (first pass has number 0 assigned) we must build
  539. that 32 additional equations (done in set_eax()).
  540.      Remember  when  the  process  of  XORing  was  stopped, and next pass was
  541. begining?  When  the  AH  was  0dh.  So,  when  the  0dh put after password by
  542. int21h/ah=0a  function  is  inside  the 12-byte snip, it's being XORed by some
  543. values  from  table and there's no 0dh to stop. The nearest 0dh is on the 14th
  544. position,  and  that's why when we have less then 12 chars in password we must
  545. set passsize after first pass to 14.
  546.  
  547.  
  548. ------------------------------------------------------------------------------
  549. create_equations()
  550. ------------------------------------------------------------------------------
  551.  
  552.      This function converts data stored in TabCipher to equations (also stored
  553. in  TabCipher).  The  target_table,  used  for  creating  right  hand  side of
  554. equations is store in XOR.DAT file, which is a dump from TEST4.COM
  555.  
  556. ------------------------------------------------------------------------------
  557. solve()
  558. ------------------------------------------------------------------------------
  559.  
  560.      This   function   solves   the   equations   created   in   TabCipher  by
  561. create_equations() using Gauss-Jordan method. Let me show you the algorithm on
  562. example.
  563.  
  564. Let's say we've got following set of equations
  565.  
  566. a xor b xor d = 1
  567. c xor d = 0
  568. a xor c xor d = 1
  569. a xor c = 0
  570.  
  571. It can be written also as
  572.  
  573. 1*a xor 1*b xor 0*c xor 1*d = 1
  574. 0*a xor 0*b xor 1*c xor 1*d = 0
  575. 1*a xor 0*b xor 1*c xor 1*d = 1
  576. 1*a xor 0*b xor 1*c xor 0*d = 0
  577.  
  578. Writing it in compact form:
  579.  
  580. 1101 1
  581. 0011 0
  582. 1011 1
  583. 1010 0
  584.  
  585. It's the format the equations are stored in TabCipher after create_equations()
  586. function was called. The Gauss-Jordan algorithm works like this:
  587.  
  588. Let's eliminate 1 from the first column, leaving it just in first equation.
  589. How? By XORing all equations with 1 in the first column by first equation.
  590.  
  591. 1101 1
  592. 0011 0
  593. 0110 0 <- 1101 xor 1011 = 0110, 1 xor 1 = 0
  594. 1010 0
  595.  
  596. And XOR also fourth equation:
  597.  
  598. 1101 1
  599. 0011 0
  600. 0110 0
  601. 0111 1 <- 1101 xor 1010 = 0111, 1 xor 0 = 1
  602.  
  603. We haven't got 1 on second column and second row, so let's exchange second
  604. equation with third.
  605.  
  606. 1101 1
  607. 0110 0 \
  608. 0011 0 /
  609. 0111 1
  610.  
  611. Let's eliminate 1 from second column (except second row), firstly XOR first
  612. equation with second
  613.  
  614. 1011 1 <- 1101 xor 0110 = 1011, 1 xor 0 = 1
  615. 0110 0
  616. 0011 0
  617. 0111 1
  618.  
  619. Now XOR fourth equation by second
  620.  
  621. 1011 1
  622. 0110 0
  623. 0011 0
  624. 0001 1 <- 0111 xor 0110 = 0001, 1 xor 0 = 1
  625.  
  626. Do the same with third column.
  627.  
  628. 1000 1
  629. 0101 0
  630. 0011 0
  631. 0001 1
  632.  
  633. And, of course with last, fourth.
  634.  
  635. 1000 1
  636. 0100 1
  637. 0010 1
  638. 0001 1
  639.  
  640.      The  result is on the right hand side - first bit in first row, second in
  641. second,  and  so  on. In my solve() I'm using a variation of this algorithm. I
  642. don't  swap the equations, but I set appropriate bit in solved table. When bit
  643. is  set  in the solved table, that means this equation was used as a "base" to
  644. calculate  one of the bits. More details in the source code - if you want know
  645. how it works - study it.
  646.  
  647.  
  648.                                After testcrk.c
  649.  
  650.  
  651.      After  running  testcrk  you'll get two new files - test.out and equ.dat.
  652. Reading  the  first one will bring first success - second and third bytes are,
  653. respectively,  'a'  and  't'.  EVERY valid, 12-char, password has to have "at"
  654. string  on the second and third chars. I've written a showequ.c which converts
  655. equ.dat  into  equ.txt  - human readable form. If you have thoroughly examined
  656. testcrk.c  you'll  also be able to understand showequ.c with ease. Run showequ
  657. and read equ.txt. The only two additional (to "at" string) conditions are:
  658.  
  659. 1. password[1] = password[12] xor 6
  660. 2. password[4] = password[5] xor password[6] xor ... xor password[11] xor
  661.    password[1] xor 57
  662.  
  663.      Just  these  three conditions should be met to generate a VALID password!
  664. (Look   into   genpass.c   for   details)  BTW:  The original password used by
  665. LordByte was "saturn404cpu" (try typing rn404cpu into genpass ;)
  666.  
  667.  
  668.               Hey! Password generated by genpass.c doesn't work!
  669.  
  670.  
  671.      The reason for this is very simple. Remember how test4 checks if it's the
  672. end of the password and it should begin next pass? It's checking for 0dh in ah
  673. register.  When  0dh appears in some strange place (after xoring password with
  674. values  from  the  table),  the  schema of xoring changes dramatically, so the
  675. equations  produced  by  testcrk.c  are  useless, what makes password bad. Try
  676. entering  "KurwaMac"  (pozdrowienia  dla wszystkich Polakow <- sorry, a bit of
  677. Polish here) into genpass, and then generated password into test4. Then run TD
  678. and look where this mysterious 0dh is appearing in the password.
  679.  
  680.  
  681.  
  682.                               Counting password
  683.  
  684.  
  685.      I  don't  know  the  exact  number  of passwords, that can be accepted by
  686. test4.   However,   using   calculus   of  probability,  I  give  you  a  good
  687. approximation.  As  shown  in  the  previous paragraph, there is 8 significant
  688. (changeable)  chars in password, 2 of chars are "checksums" of this eight, and
  689. 2 are constant ("at"). So, theoretically, there is 2^(8*8) passwords, which is
  690. 2^64.  But  you must remember about 0dh appearing in the password after XORing
  691. it.  Let's assume (I don't know if it's right assumption. If you can give me a
  692. strict  mathemathical  proof,  I  would  be  pleased.  Send all your tries to:
  693. croock@priv.onet.pl)  that  appearing  0dh  on  each  of 12 positions has same
  694. likelihood.  There  are  4  passes  where  0dh  can  appear, so it gives us 48
  695. possible  positions. The likelihood of appearing 0dh in one position is like 1
  696. to  256. So the sumary likelihood of appearing at least one 0dh in password is
  697. 48/256, which is equal to 3/16. So, 3/16 of passwords has 0dh inside.
  698.  
  699. 3             3 * 2^64
  700. --  * 2^64 = --------- = 3 * 2^60
  701. 16              2^4
  702.  
  703.      So, the probable number of passwords equals to:
  704.  
  705. 2^64 - 3 * 2^60 = 2^60 * (2^4 - 3) = 13 * 2^60 ~= 2^64
  706.  
  707.      As  stated  above,  this is only good approximation. Why? Maybe there are
  708. some passwords with 0dh, which are good ones. Maybe the the likelihood on each
  709. position is not the same. Maybe... However, the number of passwords is so big,
  710. it makes no difference ;)
  711.  
  712.                                  Final words
  713.  
  714.  
  715.      I  hope  you understand this whole crap I wrote above, and I think you'll
  716. find  it  useful.  If  you have any comments, questions or some remarks please
  717. write to croock@priv.onet.pl.
  718.      Message  to  all  lamahows:  don't  steal my code, it is supposed to be a
  719. learning  assistance,  not the occasion to change CR00CK to your nick and tell
  720. the whole world how good you are.
  721.      Greetz  must  go  to  LordByte  for  his test4 and Razzia for his (moral)
  722. support ;)
  723.  
  724.                               Really final words
  725.  
  726.  
  727.      Look  out!  TEST5 is going out. Search for another tutorial by me, now on
  728. cracking test5 :-)))
  729.  
  730.                                                             mat=ByCr00ck
  731.                                                             1at:14061997
  732.